package com.miyake.dsp.otdr;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import com.miyake.dsp.common.CommonTool;

public class Sr4731Parser {
	class StC_map {
		int revNo;
		int size;
		String name;
	};
	
	private char[] trace;

	public Sr4731Parser(byte[] bin) {
		parse(bin);
	}
	
	public Sr4731Parser(String filename) {
		try {
			BufferedInputStream is = new BufferedInputStream(new FileInputStream(new File(filename)));
			byte[] b = new byte[is.available()];
			is.read(b, 0, is.available());
			parse(b);
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	private void parse(byte[] b) {
		if (isSr4731(b)) {
			int blockCount = bin2short(b, 10);
			
			int bpos = bin2int(b, 6);
			int ipos = 12;
			StC_map bl = getBlockIndex(b, ipos - 6);
			for (int i = 0; i < blockCount - 1; i++) {
				StC_map prev = bl;
				ipos += bl.name.length() + 7;
				if(b[ipos] == 0) ipos++;
		        bl = getBlockIndex(b, ipos-6);
		        decode(b, prev.name, bpos);
	            bpos += bl.size;
			}

		}
		else {
			System.out.println("Not OTDR file");
		}
	}

	private void decode(byte[] b, String name, int bpos) {
		if (name.equals("DataPts")) {
			readTrace(b, bpos);
			
		}
	}

	private void readTrace(byte[] b, int bpos) {
		int size = bin2int(b, bpos = bpos + 8); // 4
		short scaleFactor = bin2short(b, bpos = bpos + 4); // 2
		int tps = bin2short(b, bpos = bpos+ 2); //
		short sf = bin2short(b, bpos = bpos + 4);
		trace = new char[size];
		for (int i = 0; i < size; i++) {
			trace[i] = (char)bin2short(b, bpos = bpos + 2);
//			System.out.println(trace[i]);
		}
	}

	private long bin2long(byte[] b, int offset) {
		return bin2num(b, offset, 8);
	}

	private short bin2short(byte[] b, int offset) {	
		return (short)bin2num(b, offset, 2);
	}

	private long bin2num(byte[] b, int offset, int size) {
		long ret = 0;
		for (int i = 0; i < size; i++) {
			ret += (b[offset + i] & 0xff) << (i * 8);
		}
		return ret;
	}
	
	private int bin2int(byte[] b, int offset) {
		return (int)bin2num(b, offset, 4);
	}

	private String bin2str(byte[] b, int offset) {
		int i = offset;
		char c;
		String ret = "";
		while( (c = (char)b[i++]) != 0x00) {
			ret += c;
		}
		return ret;
	}
	
	private boolean isSr4731(byte[] b) {
		return bin2str(b, 0).equals("Map");
	}
	
	public char[] getTrace() {
		return trace;
	}
	
	public double[] getTraceDouble() {
		double[] ret = new double[trace.length];
		
		for (int i = 0; i < ret.length; i++) {
			ret[i] = (double)trace[i];
		}
		double max = CommonTool.getMaxValue(ret);
		for (int i = 0; i < ret.length; i++) {
			ret[i] = (max - ret[i])/1000.0;
		}		
		return ret;
	}
	
	private StC_map getBlockIndex(byte[] b, int startIndex) {
		StC_map ret = new StC_map();
		ret.revNo = bin2short(b, startIndex);
		ret.size = bin2int(b, startIndex + 2);
		ret.name = bin2str(b, startIndex + 6);
		return ret;
	}
}
